\section{对象大小与对齐}

\subsection{sizeof的使用场合}
\cite{pibible}P55。

\subsection{常见类型的大小}
\begin{itemize}
    \item string:4
    \item istream:144
    \item vector:13
    \item 空类：1
    \item 多重继承空类：1
    \item 虚继承空类：4. 因为涉及虚表(\cite{pibible}P59)
\end{itemize}

\subsection{成员变量地址偏移求取}
以下宏可用于求取对象obj的成员变量m相对于对象起始字节的地址偏移\cite{pibible}：
\begin{lstlisting}
    #define MEM_VAR_SHIFT(obj, m) (size_t)&(((obj*)0)->m)
\end{lstlisting}
将地址零强制转换为所关心的类型，则各字段的地址等于其相对于0的偏移。只要不引用各字段，就不会发生段错误。

\subsection{变量对齐规则}
内存中的数据对齐准则，指数据所在内存地址必须是数据长度的整数倍(\cite{pibible}P50)。当在栈上分配变量空间时，这一点由编译器保证，且不同的编译器会输出不同的结果。当在堆上分配大片空间，由程序员故意在非变量长度整数倍的地址上存放一变量，这一点可能无法保证。

对于成员变量对齐规则,有
参\cite{pibible}P49。
\begin{enumerate}
    \item 如果成员均小于处理器位数，以最长成员为对齐单位
    \item 如果存在成员达到或超过处理器位数，则以处理器位数为对齐单位
    \item 类型相同的连续元素位于连续的空间内，如同数组(只要第一个元素满足内存中的数据对齐规则，其后元素必然满足对齐规则)。
    \item 对象的大小为对齐单位的整数倍
\end{enumerate}

VC++中加上\#pragma pack(n)的设定能取消数据对齐，按照字节存储。

使用g++测试，总结出如下规律:
    成员变量如果是结构体，则分解开考虑，相当于所有成员的长度只能是1,2,4,8。如果32位机上出现了4字节或8字节的变量，则结构长度为4字节的倍数，而每个成员均须保证自身是对齐的(假设结构体起始于4字节倍数地址)。如果最长的成员长2字节，则结构长度为2字节的倍数。如果是由单字节变量聚合成，则无需考虑对齐。


另外，在栈上分配结构体空间，是如何确定起始地址的？可以猜想，如果确保结构体起始于4字节倍数的地址，则可以保证每个成员都是对齐的。但实际分配原则应比此宽松。




